import logging
import os
import platform
import smtplib
import subprocess
import tkinter as tk
from datetime import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from tkinter import ttk

import winsound
from win10toast_click import ToastNotifier

from notify.notification_manager import NotificationType, NotificationConfig
from utils.file_util import FileUtil


class NotificationSender:
    """多通道通知发送器"""

    def __init__(self, config: NotificationConfig, tray_icon=None, root=None):
        self.config = config
        self.tray_icon = tray_icon
        self.root = root
        self.logger = self._setup_logger()

    def _setup_logger(self):
        """设置日志记录器"""
        logger = logging.getLogger("NotificationSystem")
        logger.setLevel(logging.INFO)

        # 文件日志处理器
        log_file = self.config.get_setting("log_settings", "file_path", "notifications.log")
        file_handler = logging.FileHandler(log_file)
        file_handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
        logger.addHandler(file_handler)

        return logger

    def send(self, title, message, task=None):
        callback = None
        if len(task.attachments):
            callback = lambda: FileUtil.open_file_directory(task.attachments[0])
        """发送通知到所有启用的通道"""
        methods = {
            NotificationType.TRAY_BUBBLE: self._send_tray_notification,
            NotificationType.WINDOWS_TOAST: lambda _t, _m, _tk: self._send_windows_toast(_t, _m, _tk, callback),
            NotificationType.SOUND: self._play_sound,
            NotificationType.EMAIL: self._send_email,
            NotificationType.DESKTOP_POPUP: self._show_desktop_popup,
            NotificationType.LOG_FILE: self._log_to_file,
            NotificationType.SYSTEM_LOG: self._log_to_system,
            NotificationType.CUSTOM_SCRIPT: self._run_custom_script
        }

        for method_type, method_func in methods.items():
            if self.config.is_method_enabled(method_type):
                try:
                    method_func(title, message, task)
                except Exception as e:
                    self.logger.error(f"发送{method_type.value}通知失败: {str(e)}")

    def _send_tray_notification(self, title, message, task=None, callback=None):
        self.logger.info("tray_icon")
        """发送托盘气泡通知"""
        if self.tray_icon:
            self.root.after(0, lambda: self.tray_icon.notify(title=title, message=message))

    def _send_windows_toast(self, title, message, task=None, callback=None):
        self.logger.info("windows_toast")
        """发送Windows Toast通知"""
        if platform.system() == "Windows":
            duration = self.config.get_setting("windows_toast", "duration", 24 * 60 * 60)
            toaster = ToastNotifier()
            toaster.show_toast(
                title,
                message,
                duration=duration,
                threaded=True,
                callback_on_click=callback
            )

    def _play_sound(self, title, message, task=None):
        self.logger.info("play_sound")
        """播放声音提醒"""
        if self.config.get_setting("sound_settings", "enabled", False):
            sound_file = self.config.get_setting("sound_settings", "file_path", "alarm.wav")
            try:
                winsound.PlaySound(sound_file, winsound.SND_FILENAME | winsound.SND_ASYNC)
            except:
                # 回退到系统默认声音
                winsound.MessageBeep()

    def _send_email(self, title, message, task=None):
        self.logger.info("send_email")
        """发送邮件通知"""
        if self.config.get_setting("email_settings", "enabled", False):
            settings = self.config.config["email_settings"]

            msg = MIMEMultipart()
            msg['Subject'] = f"[任务提醒] {title}"
            msg['From'] = settings["username"]
            msg['To'] = settings["recipient"]

            # 创建HTML格式的邮件内容
            html = f"""<html>
                <body>
                    <h2>任务提醒: {title}</h2>
                    <p>{message.replace('\n', '<br>')}</p>
                    {self._get_task_html(task) if task else ''}
                </body>
            </html>"""

            msg.attach(MIMEText(html, "html"))

            with smtplib.SMTP(settings["smtp_server"], settings["smtp_port"]) as server:
                server.starttls()
                server.login(settings["username"], settings["password"])
                server.send_message(msg)

    def _get_task_html(self, task):
        """生成任务信息的HTML"""
        days_left = (task.due_date - datetime.now().date()).days
        return f"""
            <div style="margin-top: 20px; border-top: 1px solid #eee; padding-top: 10px;">
                <h3>任务详情</h3>
                <p><b>截止日期:</b> {task.due_date.strftime('%Y-%m-%d')}</p>
                <p><b>剩余时间:</b> {days_left}天</p>
                <p><b>优先级:</b> {task.priority.value}</p>
                <p><b>状态:</b> {task.status.value}</p>
                <p><b>描述:</b> {task.description}</p>
            </div>
        """

    def _show_desktop_popup(self, title, message, task=None):
        self.logger.info("show_desktop_popup")
        """显示桌面弹窗"""
        duration = self.config.get_setting("desktop_popup", "duration", 5) * 1000

        def show_popup():
            popup = tk.Toplevel()
            popup.title(title)
            popup.attributes("-topmost", True)
            popup.geometry("300x200+100+100")
            popup.overrideredirect(True)  # 无边框窗口

            # 设置窗口位置
            position = self.config.get_setting("desktop_popup", "position", "bottom-right")
            screen_width = popup.winfo_screenwidth()
            screen_height = popup.winfo_screenheight()

            if position == "top-left":
                popup.geometry(f"+10+10")
            elif position == "top-right":
                popup.geometry(f"+{screen_width - 310}+10")
            elif position == "bottom-left":
                popup.geometry(f"+10+{screen_height - 210}")
            else:  # bottom-right
                popup.geometry(f"+{screen_width - 310}+{screen_height - 210}")

            # 内容区域
            frame = ttk.Frame(popup, padding=10)
            frame.pack(fill=tk.BOTH, expand=True)

            ttk.Label(frame, text=title, font=("Arial", 12, "bold")).pack(anchor=tk.W)
            ttk.Label(frame, text=message, wraplength=280).pack(anchor=tk.W, pady=5)

            # 关闭按钮
            ttk.Button(frame, text="关闭", command=popup.destroy).pack(side=tk.BOTTOM, pady=5)

            # 自动关闭
            popup.after(duration, popup.destroy)

        # 在主线程显示弹窗
        self.root.after(0, show_popup)

    def _log_to_file(self, title, message, task=None):
        """记录到日志文件"""
        self.logger.info(f"{title} - {message}")

    def _log_to_system(self, title, message, task=None):
        """记录到系统日志"""
        if platform.system() == "Windows":
            import win32evtlogutil
            win32evtlogutil.ReportEvent(
                "TaskReminder",
                1,  # 信息类型
                eventType=win32evtlogutil.EVENTLOG_INFORMATION_TYPE,
                strings=[f"{title}: {message}"]
            )

    def _run_custom_script(self, title, message, task=None):
        """执行自定义脚本"""
        script_path = self.config.get_setting("custom_script", "path")
        if script_path and os.path.exists(script_path):
            params = self.config.get_setting("custom_script", "parameters", "")
            full_cmd = f'"{script_path}" {params} "{title}" "{message}"'
            subprocess.Popen(full_cmd, shell=True)

    # 其他通知类型可在此扩展...
